/*  This file is part of Paxer.

    CASpp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CASpp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CASpp.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2014 Jérome LAURENS

    See https://code.google.com/p/idalgo/

*/

instructions(lhs) ::= instruction(rhs).     { lhs = rhs; }

//instruction ::= expression.
instruction(lhs) ::= expression(rhs).       { lhs = rhs; }

expression(lhs) ::= Symbol(rhs).            { PaxerRuntimeAssert(rhs->isSymbol());lhs = rhs;}

expression(lhs) ::= list(rhs).             { lhs = rhs; }

list(lhs) ::= list_begin(a) list_end(b). {
    lhs = CASpp::makeListNodeRef("");
    std::cout << "List created: " << lhs->listRef()->longDescription() << std::endl;
}

list_begin(lhs) ::= LIST_BEGIN. {
    lhs = CASpp::makeListNodeRef("");
    std::cout << "List created (void)"<< std::endl;
}

list(lhs) ::= list_begin LIST_END. {
    lhs = CASpp::makeListNodeRef("");
    std::cout << "List created: " << lhs->listRef()->longDescription() << std::endl;
}
list(lhs) ::= LIST_BEGIN list_content(rhs) LIST_END. {
    lhs = rhs;
    std::cout << "List created: " << lhs->listRef()->longDescription() << std::endl;
}
list_content(lhs) ::= expression(rhs). {
    lhs = CASpp::makeListNodeRef("");
    lhs->push_back(rhs);
    std::cout << "List created: " << lhs->listRef()->longDescription() << std::endl;
}

list_content(lhs) ::= list_content(a) LIST_SEP expression(b). {
    PaxerRuntimeAssert(a->push_back(b));
    lhs = a;
    std::cout << "List augmented: " << lhs->listRef()->longDescription() << std::endl;
}

expression(lhs) ::= vector(rhs).    { lhs = rhs; }

vector(lhs) ::= VECTOR_BEGIN list_content(rhs) VECTOR_END. {
    PaxerRuntimeAssert(rhs->isList());
    lhs = CASpp::makeVectorNodeRef("");
    lhs->vectorRef()->swap(*rhs->listRef());
}

%ifdef RIEN
vector(lhs) ::= VECTOR_BEGIN list(rhs) VECTOR_END. {
    PaxerRuntimeAssert(rhs->isVector());
    lhs = rhs;
}
instruction(lhs) ::= list(rhs).             {lhs = rhs;}

expression(lhs) ::= Variable(rhs).          {PaxerRuntimeAssert(rhs->isVariable());lhs = rhs;}
expression(lhs) ::= Symbol(rhs).            {PaxerRuntimeAssert(rhs->isSymbol());lhs = rhs;}
expression(lhs) ::= Integer(rhs).           {PaxerRuntimeAssert(rhs->isInteger());lhs = rhs;}
expression(lhs) ::= Rational(rhs).          {PaxerRuntimeAssert(rhs->isRational());lhs = rhs;}
expression(lhs) ::= Real(rhs).              {PaxerRuntimeAssert(rhs->isReal());lhs = rhs;}

list(lhs) ::= expression(a) LIST_SEP expression(b). {
    lhs = CASpp::makeListNodeRef("");
    lhs->listRef()->push_back(a);
    lhs->listRef()->push_back(b);
}

list(lhs) ::= list(a) LIST_SEP expression(b). {
    PaxerRuntimeAssert(a->isList());
    a->listRef()->push_back(b);
    lhs = a;
}

vector(lhs) ::= VECTOR_BEGIN list(rhs) VECTOR_END. {
    PaxerRuntimeAssert(rhs->isList());
    lhs = CASpp::makeVectorNodeRef("");
    lhs = rhs;
}

expression(lhs) ::= vector(rhs).    { lhs = rhs; }

function(lhs) ::= Symbol(a) VECTOR_BEGIN list(b) VECTOR_END. {
    PaxerRuntimeAssert(a->isSymbol());
    PaxerRuntimeAssert(b->isList());
    lhs = CASpp::makeFunctionNodeRef(a->symbolRef()->name());
}

expression(lhs) ::= function(rhs).    { lhs = rhs; }

%endif

%ifdef GORBI
%left OR.
%left AND.
%nonassoc EQ NE GT GE LT LE.
%left PLUS MINUS.
%left TIMES DIVIDE MODULO.
%right EXP NOT LOG.

instructions(lhs) ::= instruction(rhs).     {lhs = rhs;}
instruction(lhs) ::= expression(rhs).       {lhs = rhs;}

expression(lhs) ::= Variable(rhs).          {PaxerRuntimeAssert(rhs->isVariable());lhs = rhs;}
expression(lhs) ::= Symbol(rhs).            {PaxerRuntimeAssert(rhs->isSymbol());lhs = rhs;}
expression(lhs) ::= Integer(rhs).           {PaxerRuntimeAssert(rhs->isInteger());lhs = rhs;}
expression(lhs) ::= Rational(rhs).          {PaxerRuntimeAssert(rhs->isRational());lhs = rhs;}
expression(lhs) ::= Real(rhs).              {PaxerRuntimeAssert(rhs->isReal());lhs = rhs;}

list(lhs) ::= expression(a) LIST_SEP expression(b). {
    lhs = CASpp::makeVectorNodeRef("");
    lhs->vectorRef()->push_back(a);
    lhs->vectorRef()->push_back(b);
}

list(lhs) ::= list(a) LIST_SEP expression(b). {}

expression ::= expression PLUS expression.  { std::cout << "SOMME" << std::endl; }
expression ::= expression MINUS expression. { std::cout << "DIFFERENCE" << std::endl; }
expression ::= expression TIMES expression.  { std::cout << "PRODUIT" << std::endl; }
expression ::= expression DIVIDE expression.{ std::cout << "QUOTIENT" << std::endl; }
instruction ::= Variable TAKES expression. { std::cout << "variable assignment" << std::endl; }

instruction ::= Symbol TAKES expression. { std::cout << "symbol assignment" << std::endl; }

instructions ::= instructions SEPARATOR instruction.
%endif
